#ifndef HASH_INDEX_H
#define HASH_INDEX_H

#include "index_manager.h"
#include "../memory/memory_manager.h"
#include <stdint.h>
#include <stdbool.h>
#include <stdatomic.h>
#include <pthread.h>

// Hash index configuration
#define HASH_INDEX_DEFAULT_BUCKETS     1024
#define HASH_INDEX_MAX_LOAD_FACTOR     0.75
#define HASH_INDEX_MIN_LOAD_FACTOR     0.25
#define HASH_INDEX_GROWTH_FACTOR       2
#define HASH_INDEX_MAX_CHAIN_LENGTH    8

// Forward declarations
typedef struct hash_index hash_index_t;
typedef struct hash_bucket hash_bucket_t;
typedef struct hash_entry hash_entry_t;
typedef struct hash_iterator hash_iterator_t;

// Hash entry - stores a key-value pair
struct hash_entry {
    void* key;                      // Key data
    size_t key_size;               // Key size
    void* value;                   // Value data  
    size_t value_size;             // Value size
    uint32_t hash_value;           // Cached hash value
    struct hash_entry* next;       // Next entry in chain
};

// Hash bucket - contains a chain of entries
struct hash_bucket {
    hash_entry_t* head;            // Head of entry chain
    uint32_t count;                // Number of entries in bucket
    pthread_mutex_t mutex;         // Bucket-level mutex for fine-grained locking
};

// Hash index iterator
struct hash_iterator {
    hash_index_t* index;           // Index reference
    uint32_t current_bucket;       // Current bucket index
    hash_entry_t* current_entry;   // Current entry
    bool is_valid;                 // Iterator validity
    
    // Range scan parameters (for ordered iteration)
    void* start_key;               // Start key (NULL for full scan)
    size_t start_key_size;         // Start key size
    void* end_key;                 // End key (NULL for full scan)
    size_t end_key_size;           // End key size
    bool forward;                  // Scan direction (always true for hash)
};

// Hash index structure
struct hash_index {
    // Core hash table
    hash_bucket_t* buckets;        // Array of hash buckets
    uint32_t bucket_count;         // Number of buckets
    uint32_t entry_count;          // Total number of entries
    
    // Configuration
    double max_load_factor;        // Maximum load factor before resize
    double min_load_factor;        // Minimum load factor before shrink
    uint32_t max_chain_length;     // Maximum chain length before resize
    
    // Memory management
    memory_manager_t* memory_mgr;  // Memory manager
    
    // Thread safety
    pthread_rwlock_t resize_lock;  // Global resize lock
    atomic_bool is_resizing;       // Resize in progress flag
    
    // Statistics
    uint64_t total_operations;     // Total operations
    uint64_t searches;             // Search operations
    uint64_t inserts;              // Insert operations
    uint64_t deletes;              // Delete operations
    uint64_t updates;              // Update operations
    uint64_t collisions;           // Hash collisions
    uint64_t rehashes;             // Number of rehash operations
    uint64_t chain_traversals;     // Total chain traversals
    
    // Hash function state
    uint32_t hash_seed;            // Random seed for hash function
};

// Hash index API

// Creation and destruction
hash_index_t* hash_index_create(memory_manager_t* memory_mgr, 
                                uint32_t initial_buckets,
                                double max_load_factor);
void hash_index_destroy(hash_index_t* index);

// Core operations
index_result_t hash_index_insert(hash_index_t* index, 
                                const void* key, size_t key_size,
                                const void* value, size_t value_size);
index_result_t hash_index_delete(hash_index_t* index, 
                                const void* key, size_t key_size);
index_result_t hash_index_update(hash_index_t* index,
                                const void* key, size_t key_size,
                                const void* value, size_t value_size);
index_result_t hash_index_search(hash_index_t* index,
                                const void* key, size_t key_size,
                                index_search_result_t* result);

// Iterator operations (for full table scan)
hash_iterator_t* hash_index_iterator_create(hash_index_t* index);
bool hash_iterator_valid(hash_iterator_t* iter);
index_result_t hash_iterator_next(hash_iterator_t* iter);
index_result_t hash_iterator_current(hash_iterator_t* iter,
                                    void** key, size_t* key_size,
                                    void** value, size_t* value_size);
void hash_iterator_destroy(hash_iterator_t* iter);

// Bulk operations
index_result_t hash_index_bulk_insert(hash_index_t* index,
                                     const void** keys, size_t* key_sizes,
                                     const void** values, size_t* value_sizes,
                                     size_t count);

// Management operations
index_result_t hash_index_clear(hash_index_t* index);
index_result_t hash_index_rebuild(hash_index_t* index);
bool hash_index_validate(hash_index_t* index);

// Statistics and monitoring
void hash_index_get_stats(hash_index_t* index, index_stats_t* stats);
void hash_index_print_stats(hash_index_t* index);
double hash_index_get_load_factor(hash_index_t* index);
uint32_t hash_index_get_max_chain_length(hash_index_t* index);

// Configuration
index_result_t hash_index_set_max_load_factor(hash_index_t* index, double factor);
index_result_t hash_index_set_max_chain_length(hash_index_t* index, uint32_t length);

// Internal operations
uint32_t hash_function(const void* key, size_t key_size, uint32_t seed);
uint32_t hash_function_djb2(const void* key, size_t key_size);
uint32_t hash_function_fnv1a(const void* key, size_t key_size);
uint32_t hash_function_murmur3(const void* key, size_t key_size, uint32_t seed);

// Bucket operations
hash_entry_t* hash_bucket_find(hash_bucket_t* bucket, const void* key, size_t key_size,
                              uint32_t hash_value);
index_result_t hash_bucket_insert(hash_bucket_t* bucket, hash_entry_t* entry,
                                 memory_manager_t* memory_mgr);
index_result_t hash_bucket_delete(hash_bucket_t* bucket, const void* key, size_t key_size,
                                 uint32_t hash_value, memory_manager_t* memory_mgr);

// Entry operations
hash_entry_t* hash_entry_create(memory_manager_t* memory_mgr,
                               const void* key, size_t key_size,
                               const void* value, size_t value_size,
                               uint32_t hash_value);
void hash_entry_destroy(hash_entry_t* entry, memory_manager_t* memory_mgr);
int hash_entry_key_compare(const hash_entry_t* entry, const void* key, size_t key_size);

// Resize operations
index_result_t hash_index_resize(hash_index_t* index, uint32_t new_bucket_count);
bool hash_index_should_resize(hash_index_t* index);
uint32_t hash_index_next_bucket_count(uint32_t current_count, bool grow);

// Key comparison utilities
int hash_key_compare(const void* key1, size_t key1_size, 
                    const void* key2, size_t key2_size);

// Interface adapter for index manager
index_interface_t* hash_index_interface_create(void);

#endif // HASH_INDEX_H